一、AWR 分析DB Time : 2,739.51 (mins)等待事件:enq: TX - index contention常出现在高并发场景下,由于索引分裂产生的竞争等待。 enq: TX - index contention事件,导致此表的插入、更新变慢,从而导致订单超时失败。 : TX - index contention事件出现频率。 四、测试Hash索引对enq: TX - index contention 降低影响1、创建分区表:T1;索引:pk_t1_id create table t1 ( id varchar2( : TX - index contention 消失Segments by ITL Waits 变化:No data exists9、测试对比小结:由此对比Hash索引降低enq: TX - index
专家解答 查看故障期间的ash信息,发现在应用异常的时间段内,SQL_ID为g64z3fw1nffvj的insert操作产生了大量的enq: TX - index contention等待,并且造成这个等待事件的原因就是 alter database操作和它本身的insert操作,在resize的执行过程中enq: TX - index contention等待事件一直升高,resize操作成功后(即2019-08-22 : TX - index contention' Chain 1 Signature Hash: 0xbeca5ef7 [b] Chain 2 Signature: <not in a wait ><='buffer busy waits'<='<em>enq</em>: <em>TX</em> - <em>index</em> contention' Chain 2 Signature Hash: 0xbeca5ef7 [c] Chain : TX - index contention' Chain 1 Signature Hash: 0xbeca5ef7 -----------------------------------------
综上,3个连接数堆积的异常时刻TOP event都是 “enq: TX - row lock contention”。
♣ 问题 队列等待之enq: TX - allocate ITL entry ♣ 答案 1、故障环境介绍 项目 Source db db类型 RAC db version 11.2.0.3.0 db AWR的其它部分就不分析了,首先这个等待事件“enq: TX - allocate ITL entry”在MOS(Troubleshooting waits for 'enq: TX - allocate 如果事务申请不到新的可用ITL槽时,就会产生enq: TX - allocate ITL entry等待。 如果表中经常执行UPDATE语句,那么就会导致块中剩余的10%空间所剩无几,而且在业务的并发量很大的情况下,此时就更容易遇到enq: TX - allocate ITL entry等待。 <index_name> rebuild PCTFREE 40 INITRANS 50; 3、故障分析及解决 目前首先需要找到产生等待事件的表,然后修改其INITRANS和PCTFREE来重构表就可以了
Objects ADDMRPT 报告 Summary of Findings Finding 2: Row Lock Waits 应用确认 写在最后 前言 最近看 awr 报告时,经常会看到一些 enq : TX - row lock contention 的等待事件,所以简单研究一下如何排查,仅为个人所见,如有异议或者修正还请评论指出,谢谢! 通常,产生enq: TX - row lock contention事件的原因有以下几种可能: 不同的session更新或删除同一条记录; 唯一索引有重复索引; 位图索引同时被更新或同时并发的向位图索引字段上插入相同字段值 查看监控服务器,发现数据库存在 enq: TX - row lock contention 锁的情况。 排查 首先确认发生问题的时间段,然后抓取问题时间段的报告来分析。 count(a.blocking_session) from DBA_HIST_ACTIVE_SESS_HISTORY a where event like '%enq
墨墨导读:ENQ: TX - row lock contention等待事件,是Oracle数据库里最常见的等待事件之一,一般是由于不同的session更新或删除同一条记录、唯一索引有重复索引、位图索引同时被更新或同时并发的向位图索引字段上插入相同字段值等几种可能性 表统计信息收集)and High Execution of Update sys.col_usage$(大量执行更新sys.col_usage$表) 问题表现 ---- 1)在数据库的ash中,发现大量的enq :TX – row lock contention等待事件。 = :coln DUMP LOCAL BLOCKER: initiate state dump for DEADLOCK possible owner[50.123541] on resource TX
有些问题早已进行了建议,还在修改中,但是对于第3个等待事件"enq: TX - allocate ITL entry"还是比较陌生的。准备来做一个深入的分析。 SQL> select EVENT,sid,serial# from v$session where event='enq: TX - allocate ITL entry'; EVENT : TX - allocate ITL entry 5592 25063 enq: TX - allocate 1IX C90 INDEX PARTITION 1 5.56 SYS SYSAUX WRH$_SQL_PLAN_PK INDEX 1 5.56 从上面的列表我们可以清晰的看到对于ITL wait 可以参见 Troubleshooting waits for 'enq: TX - allocate ITL entry' (Doc ID 1472175.1) 解决思路有3种 Increase
若在此分裂的过程中,有其它进程INSERT数据到该索引块中,则将进入enq: TX – index contention等待,直到分裂结束锁被释放。 :TX-index contention enq:TX-index contention是一个很常见的等待事件,其专指由于索引分裂产生的竞争等待。 : TX - index contention 14167 17838 23440717 32869104 1 enq: TX - index contention : TX - index contention 17966 18374 32976462 34443728 1 enq: TX - index contention 总 结 从测试数据分析,正常序列作为索引,在高并发的场景下,enq: TX - index contention等待次数7190,等待时间18.5s,扩展序列作为索引,在高并发的场景下,enq: TX
= 220, 这里pkts_enq 是申请2个burst_enq大小,这里应该是为了防止pkts_enq时越界吧(burst_enq默认设置为256,和vpp一次PMD读取最大256个一致。) 发包处理 接口tx发包的Hqos处理流程如下: |---VNET_DEVICE_CLASS_TX_FN (dpdk_device_class) () /*通用dpdk网卡tx处理函数*/ | | ---tx_burst_vector_internal() /*tx burst 发包函数*/ | |---rte_ring_sp_enqueue_burst() /*Hqos使能,报文入 += rte_ring_sc_dequeue_burst (swq, (void **)&pkts_enq[pkts_enq_len], hqos->hqos_burst_enq 5、网卡Tx模块判断接口使能Hqos后,报文入Hqos swq队列 6、Hqos线程对报文进行调度处理。
中,当TX锁等待获得资源后,再次查询该session,此时已经变成了空闲等待。 call started 4 --下面查询基于实例级别的等待事件 --当输入enq,则所有enq相关的等待记录会列出 goex_admin@SYBO2SZ> enq: TX - index contention 3 0 28 9 20130410 : TX - index contention 3 0 28 9 20130410 20:22:43 Concurrency : TX - index contention 3 0 28 9 20130410 20:22:43 Concurrency
Top 5 Timed Foreground Events Event Waits Time(s) Avg wait (ms) % DB time Wait Class enq: TX - row lock SUBSCRIBER_NO", "... c0m89v4d91uhh 799822736 160 1.35 read by other session 0.82 INDEX - UNIQUE SCAN : TX - row lock contention 3.77 ECC JDBC Thin Client 45/360 [ 13%] 0 3624,52345( 1) 3.01 enq: TX - row lock contention 3.01 ECC JDBC Thin Client 44/360 [ 12%] 1 6453,29237( 1) 2.83 enq: TX - row lock contention 2.83 ECC JDBC Thin Client 18/360 [ 5%] 0 793,65345( 1) 2.79 enq: TX - row lock contention 2.79 ECC JDBC
而10g之后的版本对于同一类型的enqueue也会根据情况对等待事件进行区分,例如下面介绍的TX类型的enqueue等待: Database Performance Tuning Guide 12.2 http://t.cn/RKD5CAR >10.3.7 enqueue (enq:) waits >The name of the enqueue is included as part of the wait event name, in the form enq: enqueue_type - related_details. some cases, the same enqueue type can be held for different purposes, such as the following related TX types: > >enq: TX - allocate ITL entry >enq: TX - contention >enq: TX - index contention >enq: TX -
发现这个SQL造成数据库高峰时段75%的enq: TX - row lock contention等待事件,且锁的模型是6是什么原因呢,怎样减少enq: TX - row lock contention 执行update语句期间,数据库出现enq: TX - row lock contention争用。 基于以上信息,推测之所以出现行锁争用,是这样的逻辑, ? 当对表行进行DML操作的时候,需要获取相应锁,enq: TX - row lock contention就是行锁争用,之所以出现这个争用,就是因为UPDATE用了全表扫描,导致一条SQL的执行时间比以前更久 ----------- | 0 | SELECT STATEMENT | | 1 | 35 | 0 (0)| 00:00:01 | |* 1 | INDEX ------------ | 0 | SELECT STATEMENT | | 1 | 35 | 0 (0)| 00:00:01 | |* 1 | INDEX
: TX - row lock contention -> 14518 g78jw4psdfsqc enq: TX - row lock contention -> 9505 g78jw4psdfsqc enq: TX - row lock contention -> 13090 0qpy58c2urytn enq: TX - row lock contention -> 16872 9dmsja7c69xdj enq: TX - row lock contention -> 505 85ttdm4hu93yn enq: TX - row lock contention -> 15381 0qpy58c2urytn enq: TX - row lock contention -> 13090 0qpy58c2urytn enq: TX - row lock contention -> 13756 0qpy58c2urytn enq: TX - row lock contention -> 13276 85ttdm4hu93yn enq: TX - row lock contention 但行锁占比都很平均,只能反映出SQL
| | 1 | | 1 | UPDATE | CL1_PROC_CTRL | | | | |* 2 | INDEX : TX - row lock contention 1 dch8sxwt6ujvc 4538 enq: TX - row lock contention 1 dch8sxwt6ujvc 3030 enq: TX - row lock contention 1 dch8sxwt6ujvc 7375 enq: TX - row lock contention 1 dch8sxwt6ujvc 4353 enq: TX - row lock contention : TX - row lock contention“的。
Chains most likely to have caused the hang: [a] Chain 1 Signature: 'SQL*Net message from client'<='<em>enq</em> : <em>TX</em> - row lock contention'<='<em>enq</em>: <em>TX</em> - row lock contention' Chain 1 Signature Hash: 0x42598823 [b] Chain 2 Signature: 'SQL*Net message from client'<='<em>enq</em>: <em>TX</em> - row lock contention'<='<em>enq</em>: <em>TX</em> - row : <em>TX</em> - row lock contention'<='<em>enq</em>: <em>TX</em> - row lock contention' Chain 1 Signature Hash: 0x42598823 ----- Chain 2 Signature: 'SQL*Net message from client'<='<em>enq</em>: <em>TX</em> - row lock contention'<='<em>enq</em>: <em>TX</em> - row lock
♣ 答案部分 索引分裂(Index Block Split),就是索引块的分裂。 如果此时其它会话也要修改这个索引块的数据,那么将会出现索引块的竞争,等待以“enq: TX – index contention”的形式体现,该事件是一个与索引分裂直接相关的等待事件。 若在此分裂的过程中,有其它进程INSERT数据到该索引块中,则将进入enq: TX – index contention等待,直到分裂结束锁被释放。 若主键是通过序列、时间戳或按某种规则单调生成的主键,则可以使用反转索引来有效地降低索引“单向右增长”(Right-Growing Index)的可能性。 语句如下所示: CREATE INDEX ... REVERSE; ALTER INDEX ...
: TX - row lock contention,Chain 1的会话是被sid=42的初始会话阻塞,Chain 2的会话同样被sid=42阻塞(which is a member of 'Chain Chains most likely to have caused the hang: [a] Chain 1 Signature: 'SQL*Net message from client'<='<em>enq</em> : <em>TX</em> - row lock contention' Chain 1 Signature Hash: 0x38c48850 [b] Chain 2 Signature: 'SQL*Net message from client'<='<em>enq</em>: <em>TX</em> - row lock contention' Chain 2 Signature Hash: 0x38c48850 ===== Chain 2 Signature: 'SQL*Net message from client'<='<em>enq</em>: <em>TX</em> - row lock contention' Chain 2 Signature Hash
='orderno_a'; session B --正在执行语句2,他处于enq: TX - row lock contention等待 select t.* from channel t where t where t.channel_id='ch1' for update; 可能还会有更多的session处于执行语句2,并等待enq: TX - row lock contention的情况,这里暂时只列 要知道为什么有这个疑问,就要先明白,在A执行order的for update时是已经获取了itl资源的,所以在后来真正update数据时是不应该存在这个等待的enq: TX - allocate ITL 死锁分析 ---- 要分析这个死锁就要明白等待事件enq: TX - allocate ITL entry所代表的资源itl事务槽的含义。itl事务槽是数据块头中用来标记事务的记录。 而此时,其余的很多session,比如B,C......N 等等session将块dba_2上的itl资源耗尽了,那么session A就处于等待数据块dba_2上的itl资源的状态,对应于enq: TX
='orderno_a'; session B --正在执行语句2,他处于enq: TX - row lock contention等待 select t.* from channel t where t where t.channel_id='ch1' for update; 可能还会有更多的session处于执行语句2,并等待enq: TX - row lock contention的情况,这里暂时只列 要知道为什么有这个疑问,就要先明白,在A执行order的for update时是已经获取了itl资源的,所以在后来真正update数据时是不应该存在这个等待的enq: TX - allocate ITL 死锁分析 要分析这个死锁就要明白等待事件enq: TX - allocate ITL entry所代表的资源itl事务槽的含义。itl事务槽是数据块头中用来标记事务的记录。在这里有个重点是 数据块 。 而此时,其余的很多session,比如B,C......N 等等session将块dba_2上的itl资源耗尽了,那么session A就处于等待数据块dba_2上的itl资源的状态,对应于enq: TX